# coding=utf-8
"""
author: jamon
"""
from __future__ import annotations

from typing import Optional

import ujson
from obespoir.base.common_define import DEFAULT_ID

from client.model.gate_data import GateData, GateStatus
from obespoir.share.espoir_log import global_log as logger, EspoirLog, \
    log_record

from client.model.global_data import GlobalData
from client.views.scene_mgr import scene_mgr
from package.msg_const import MsgID


class BaseHandler(EspoirLog):
    """
    基础命令处理类
    """
    def __init__(self, params, command_id: int):
        """

        :param params: dict
        :param command_id:
        """
        super().__init__()
        if not isinstance(params, dict) and params is not None:
            params = ujson.loads(params)
        self.params: dict = params
        self.command_id: int = command_id

        data = params.get("data", {})
        self.data: dict = ujson.loads(data) if isinstance(data, str) else data

        detail = self.data.get("data", {})
        self.detail: dict = ujson.loads(detail) if isinstance(detail, str) \
            else detail

    @property
    def seq(self) -> str:
        return self.params.get("seq", "")

    @property
    def code(self) -> int:
        return self.data.get("code", 0)

    def sync_default_keys(self):
        self.add_default_keys("command_id", self.command_id)

    async def execute(self, *args, **kwargs):
        raise NotImplementedError


class RegisterEvent(object):
    """
    事件管理器，将命令码与handler进行绑定
    """
    events = dict()

    def __init__(self, command_id: int):
        self.command_id: int = command_id

    def __call__(self, handler):
        self.events[self.command_id] = {"handler": handler}
        return handler


async def handle_message(msg_id: int, seq: int, session_id: Optional[str],
                         msg_data: dict):
    logger.info("start", msg_id=msg_id, seq=seq, session_id=session_id,
                msg_data=msg_data)
    await call_target(msg_id, msg_data, session_id)


async def call_target(command_id: int, data, session_id: str):
    """
    调用注册的消息处理
    :param command_id:
    :param data:
    :param session_id:
    :return:
    """
    obj = RegisterEvent.events.get(command_id, None)
    obj = obj if obj else RegisterEvent.events.get(DEFAULT_ID, None)
    # 如果没有，则进入默认消息处理
    if not obj:
        logger.warning("command_id not register",
                       command_id=command_id,
                       session_id=session_id,
                       data=data)
        return

    handler = obj.get("handler")(data, command_id)
    ret = await handler.execute()
    logger.debug("end", session_id=session_id, data=data, result=ret)
    return ret


@RegisterEvent(MsgID.LOGIN)
class LoginReplyHandler(BaseHandler):
    @log_record
    async def execute(self, *args, **kwargs):
        user_id = self.detail.get("user_id", -1)
        if -1 == user_id:
            return {}

        GlobalData().user_id = user_id
        return


@RegisterEvent(MsgID.FRAME_BROADCAST)
class GameFrameBroadcastHandler(BaseHandler):
    @log_record
    async def execute(self, *args, **kwargs):
        target_frame_no = self.detail.get("target_frame_no", 0)
        if target_frame_no:
            GateData().target_frame_no = target_frame_no

        act_records = self.detail.get("act_records", {})
        if act_records:
            GateData().add_to_acts(act_records)
        return


@RegisterEvent(MsgID.GAME_START)
class GameStartReplyHandler(BaseHandler):
    @log_record
    async def execute(self, *args, **kwargs):
        team_users = self.detail.get("team_users", [])
        GlobalData().set_team_users(team_users)
        GateData().status = GateStatus.RUNNING
        scene_mgr.switch_to_scene("battle", mode=True, gate_id=1)
        return


@RegisterEvent(MsgID.GAME_OVER)
class GameOverReplyHandler(BaseHandler):
    @log_record
    async def execute(self, *args, **kwargs):
        is_win = self.detail.get("is_win", False)
        GlobalData().is_win = is_win
        GateData().status = GateStatus.FINISHING

